<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8"/>
        <title>测试正在表达式</title>
    </head>
    <body>

    </body>

    <script>
        let hd = "houdunren2200hdcms9988";
        console.log(hd.match(/\d/g).join("")); //找到匹配的内容并连接
        // 创建正在表达式的方式
        // 方式一：在两个斜杠之间//,缺点不能放变量
        hd = "houdunren";
        console.log(/u/.test(hd)); //字符串中是否包含u,
        //方式二，可以放变量
        let u = "u";
        console.log(eval(`/${u}/`).test(hd));
        //方式三:使用对象的方式
        //let reg = new RegExp("u", "g");
        let reg = new RegExp(u, "g");
        console.log(reg.test(hd));

        console.log(/u|@/.test(hd)); //查找有a或者@符
        console.log(/aaau|@/.test(hd)); //查找匹配有aaau或者@符

        //[] 里面是或的意思
        hd = "1";
        reg = /[123]/  //匹配1或2或3
        console.log(hd.match(reg));

         //() 元数组的意思
         hd = "121234aa";
        reg = /(12|34)/  //匹配12或34
        console.log(hd.match(reg));

        //小数点需要转义\.
        //\d  0-9的数字
        //在字符串中\d其实就是d, 所以要\\d
        hd = "111.222";
        console.log(/\d+\.\d+/.test(hd));
        reg = new RegExp("\\d+\\.\\d+"); //必须要\\
        console.log(reg.test(hd));

        //边界 ^开始 $结束

        // \s表示匹配空白，例如空格、tab、\n

        hd = `
            张三: 010-99999999, 李四: 020-88888
        `;
        console.log(hd.match(/[-\d:,\s]/g));
        console.log(hd.match(/[^-\d:,\s]/g));

        //\w 数字字母下划线
        // /\w+/i i表示不区分大小写。

        // . 匹配除了换行之外的任何字符
        // 匹配所以字符[\s\S]或[\s\D]

        //忽略大小写
        hd = "houdUnren";
        console.log(hd.match(/u/ig)); // i表示不区分大小写，g表示匹配多个，否则只会打印出一个。
        console.log(hd.replace(/u/gi, "@")); //必须要有g, 否则只会替换第一个


        // /gm m表示一行一行匹配处理。
        //多行匹配
        hd = `
            #1 js,200元 #
            #2 PHP,300元 #
            #9 houdunren.com # 后盾人
            #3 node.js,180元 #
        `
        //转换为：[{name:'js',price:'200元'}]
        let lessons = hd.match(/^\s*#\d+\s+.+\s+#$/gm).map(v=>{
            console.log(v);
            v = v.replace(/\s*#\d+\s*/, "").replace(/\s+#/, "");
            [name, price] = v.split(",");
            return {name, price};
        })
        console.log(JSON.stringify(lessons, null, 2));

        // /\p{L}/gu  只匹配英文
        // /\p{P}/gu  只匹配标点
        // /\p{sc=Han}/gu 只匹配汉字

        hd = "你好abc";
        console.log(hd.match(/[你好]/gu)); //对于宽字符要加u

        hd = "houdunren";
        console.log(hd.match(/\w/g));
        reg = /\w/g;
        console.log(reg.lastIndex);
        while((res = reg.exec(hd))) {
            console.log(res);
            console.log(reg.lastIndex);
        }

        //aa123,456,bb789,
        // /\d+,?/y 和 /\d+,?/g  y和g的区别，y表示连续匹配匹配123,456，两个； g是会全局往后匹配（全局匹配）匹配123,456,789,三个；

        //中括号中.+*()都是字符本身的意思，不需要转义

        //忽略换行符 /s
        hd = `
            cyh
            gyq
        `;
        console.log(hd.match(/.+/g)); //匹配三个
        console.log(hd.match(/.+/gs)); //匹配完整的一个
        console.log(hd.match(/[\s\S]+/g)); //匹配完整的一个

        //原子组 ()
        hd = `<h1>aaa</h1><h2>bb</h2>`;
        //匹配标签内容
        reg = /<(h[1-6])>[\s\S]*<\/\1>/ig; 
        console.dir(hd.match(reg));

        //匹配邮箱： /^[\w-]+@([\w-]+\.)+(com|org|cc|cn|net)$/i

        //取出指定的内容并替换 $2
        hd = `<h1>aaa</h1><h2>bb</h2>`;
        reg = /<(h[1-6])>([\s\S]+)<\/\1>/gi;
        console.log(hd.replace(reg, `<p>$2</p>`));
        res = hd.replace(reg, (p0, p1, p2)=>{
            console.log(p0);
            console.log(p1);
            console.log(p2);
            return `<p>${p2}</p>`;
        })
        console.log(res);

        //嵌套分组(()) 和 不记录分组 (?:)
        hd = `
            https://www.houdunren.com
            http://huodunwang.com
        `;
        reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|org|cn))/i; //这样数组会有两组，0组默认整个匹配，后面的组代表小括号， 如果没有?:，会有4组
        console.dir(hd.match(reg)); //匹配所有
        console.dir(reg.exec(hd));  //下一个下一个的匹配


        //禁止贪婪(匹配少的) +?, *?,{2,100}?,{2,}?, ??
        hd = "hdddd";
        console.log(hd.match(/hd+?/));
        //比如： /<span>[\s\S]+?<\/span>/gi


        //matchAll 返回更详细的信息
        hd = "hddddhdd";
        reg = /hd+/gi;
        console.dir(hd.matchAll(reg));

        //exec完成全局匹配
        hd = "houdunren";
        reg = /u/gi;
        let result = [];
        while((res = reg.exec(hd))) {
            result.push(res);
        }
        console.log(result);

        //字符串的正则方法find和match
        //获得找到的下标 2
        console.log(hd.search(u));
        console.log(hd.search(/u/));
        //获取到匹配数组
        console.log(hd.match(/u/gi));

        hd = "2020-09-12";
        console.log(hd.split(/[-\/]/));
        console.log(hd.replace(/[-\/]/g, "/"));

        hd = "(010)9999999  (020)8888888";
        //转成 010-9999999
        reg = /\((\d{3,4})\)(\d{7,8})/g;
        console.log(hd.replace(reg, "$1-$2"))

        // $& 表示匹配的内容
        hd = "=后盾人=";
        console.log(hd.replace(/后盾人/, "11$&22")); //=11后盾人22=

        hd = "1后盾人2";
        // $` 匹配内容的前面部分内容
        console.log(hd.replace(/后盾人/, "$`")); //112

        hd = "1后盾人2";
        // $' 匹配内容的后面部分内容
        console.log(hd.replace(/后盾人/, "$'")); //122

        //原子组取别名 ?<别名>
        hd = "a1后盾人2b";
        reg = /\d(?<cyh>后盾人)\d/g;
        console.log(hd.replace(reg, "33$<cyh>44"));

        //正则方法 test
        console.log(reg.test(hd));  //true

        //正则方法exec  有些方法正则和字符串都有相同的方法名
        hd = "后盾人dadfsd后盾人";
        reg = /后盾人/g
        console.log(reg.exec(hd));

        // ?=断言匹配 指的是后面必须跟的是什么
        hd = "后盾人教程dadfsd后盾人学校";
        reg = /后盾人(?=教程)/g;  //这里面的小括号不是组。
        console.log(hd.replace(reg, "1111")); //只会匹配 后盾人教程 中的后盾人， 教程两个字不是替换内容


        // ?<= 断言匹配 指的是前面必须跟的是什么
        hd = "houdunren789hdcms666";
        reg = /(?<=houdunren)\d+/i; //小括号里面的也不是原子组
        console.log(hd.match(reg)); //789

        //手机号后4位变成*
        hd = "aa18823185102bb";
        reg = /(?<=\d{7})\d{4}/ig;
        console.log(hd.replace(reg, "****"));

        // ?! 断言匹配 指的是 后面不是什么
        // ?<! 断言匹配 指的是 前面不是什么时匹配












    </script>
    
</html>